package com.server.aspect;

import cn.hutool.core.util.StrUtil;
import com.server.annotation.HasPermission;
import com.server.constant.RedisKey;
import com.server.entity.UpmsPermission;
import com.server.exception.AccessTokenException;
import com.server.exception.PermissionException;
import com.server.component.RedisUtil;
import com.server.vo.upms.user.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;

/**
 * @ClassName HasPermission
 * @Description 权限验证
 * @Author
 * @Date 2020/4/26 16:47
 */
@Slf4j
@Component
@Aspect
public class HasPermissionAop {

    private static final String JWT_TOKEN_KEY = "_token";

    @Resource
    private RedisUtil redisUtil;

    @Pointcut("@annotation(com.server.annotation.HasPermission)")
    public void controllerNoRepeat(){}

    @Around("controllerNoRepeat()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        HttpServletRequest request =
                ((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest();
        String jwtToken = request.getHeader(JWT_TOKEN_KEY);
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature)signature;
        Method targetMethod = methodSignature.getMethod();
        if(targetMethod.isAnnotationPresent(HasPermission.class)){
            //获取方法上注解中表明的权限
            HasPermission permission = (HasPermission)targetMethod.getAnnotation(HasPermission.class);
            String roles = permission.value();
            if(StrUtil.isNotBlank(roles)) {
                UserInfo userInfo = (UserInfo) redisUtil.get(RedisKey.ADMIN_USER+":"+jwtToken);
                if(userInfo==null){
                    throw new AccessTokenException("该帐号token已失效请重新登录");
                }
                //用户的角色
                List<UpmsPermission> list = userInfo.getPermissions();
                Optional<UpmsPermission> isHave= list.stream() .filter(a -> roles.equals(a.getPermissionValue())) .findFirst();
                if (isHave.isPresent()) {
                    Object o = pjp.proceed();
                    return o;
                }else {
                    throw new PermissionException("该帐号权限不足");
                }
            }
        }
        Object o = pjp.proceed();
        return o;
    }
}
